﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using stdole;

namespace ZipStudio
{

    /// <summary>
    /// This class is trac from Roy Osherove's Blog
    /// <see cref="http://weblogs.asp.net/rosherove/archive/2008/08/02/howto-set-custom-visual-studio-addin-menu-icons-without-a-satellite-dll.aspx"/> 
    /// </summary>
    public static class IconUtils
    {

        /// <summary>
        /// Adds the command withicon.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="menuToAddTo">The menu to add to.</param>
        /// <param name="name">The name.</param>
        /// <param name="buttonText">The button text.</param>
        /// <param name="buttonDescription">The button description.</param>
        /// <param name="iconFile">The icon file.</param>
        /// <param name="addInInstance">The add in instance.</param>
        public static void AddCommandWithicon(this Commands2 root,

            CommandBarPopup menuToAddTo,

           string name,

           string buttonText,

           string buttonDescription,

           string iconFile,

           AddIn addInInstance)
        {

            object[] contextGUIDS = null;

            Command command = root.AddNamedCommand2(addInInstance,

                                                        name,

                                                        buttonText,

                                                        buttonDescription,

                                                        true, 59,

                                                        ref contextGUIDS,

                                                        (int)vsCommandStatus.vsCommandStatusSupported +

                                                        (int)vsCommandStatus.vsCommandStatusEnabled,

                                                        (int)vsCommandStyle.vsCommandStylePictAndText,

                                                        vsCommandControlType.vsCommandControlTypeButton);

            CommandBarButton control = (CommandBarButton)command.AddControl(menuToAddTo.CommandBar, 1);

            SetControlPicture(control, iconFile);

        }

        /// <summary>
        /// Adds the command withicon.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <param name="menuToAddTo">The menu to add to.</param>
        /// <param name="name">The name.</param>
        /// <param name="buttonText">The button text.</param>
        /// <param name="buttonDescription">The button description.</param>
        /// <param name="icon">The icon.</param>
        /// <param name="addInInstance">The add in instance.</param>
        public static void AddCommandWithicon(this Commands2 root,

            CommandBarPopup menuToAddTo,

           string name,

           string buttonText,

           string buttonDescription,

           Image icon,

           AddIn addInInstance)
        {

            object[] contextGUIDS = null;

            Command command = root.AddNamedCommand2(addInInstance,

                                                        name,

                                                        buttonText,

                                                        buttonDescription,

                                                        true, 59,

                                                        ref contextGUIDS,

                                                        (int)vsCommandStatus.vsCommandStatusSupported +

                                                        (int)vsCommandStatus.vsCommandStatusEnabled,

                                                        (int)vsCommandStyle.vsCommandStylePictAndText,

                                                        vsCommandControlType.vsCommandControlTypeButton);

            CommandBarButton control = (CommandBarButton)command.AddControl(menuToAddTo.CommandBar, 1);

            SetControlPicture(control, icon);

        }


        private static Color guessTransparentColor(Bitmap bitmap)
        {

            Color pixel = bitmap.GetPixel(0, 0);

            Color color2 = bitmap.GetPixel(bitmap.Width - 1, 0);

            Color color3 = bitmap.GetPixel(0, bitmap.Height - 1);

            Color color4 = bitmap.GetPixel(bitmap.Width - 1, bitmap.Height - 1);

            if (pixel == color2)
            {

                return pixel;

            }

            if (color2 == color3)
            {

                return color2;

            }

            if (color3 == color4)
            {

                return color3;

            }

            return color4;

        }





        private static Bitmap PrepareImage(Image image, Color transparentColor)
        {

            Bitmap bitmap = new Bitmap(image);

            Bitmap bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);

            Color color = guessTransparentColor(bitmap);

            for (int i = 0; i < bitmap2.Width; i++)
            {

                for (int j = 0; j < bitmap2.Height; j++)
                {

                    Color baseColor = color;

                    if ((i < bitmap.Width) && (j < bitmap.Height))
                    {

                        baseColor = bitmap.GetPixel(i, j);

                    }

                    baseColor = Color.FromArgb(0xff, baseColor);

                    if (baseColor != color)
                    {

                        bitmap2.SetPixel(i, j, baseColor);

                    }

                    else if ((transparentColor != color) && (baseColor == transparentColor))
                    {

                        if (baseColor.R > 0)
                        {

                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R - 1, baseColor.G, baseColor.B));

                        }

                        else
                        {

                            bitmap2.SetPixel(i, j, Color.FromArgb(baseColor.R + 1, baseColor.G, baseColor.B));

                        }

                    }

                    else
                    {

                        bitmap2.SetPixel(i, j, transparentColor);

                    }

                }

            }

            return bitmap2;

        }



        private static Bitmap PrepareMask(Image image)
        {

            Bitmap bitmap = new Bitmap(image);

            Bitmap bitmap2 = new Bitmap(0x10, 0x10, PixelFormat.Format24bppRgb);

            Color color = guessTransparentColor(bitmap);

            for (int i = 0; i < image.Width; i++)
            {

                for (int j = 0; j < image.Height; j++)
                {

                    Color pixel = bitmap.GetPixel(i, j);

                    Color color3 = ((pixel == color) || (pixel.A < 0xff)) ? Color.White : Color.Black;

                    bitmap2.SetPixel(i, j, color3);

                }

            }

            return bitmap2;

        }



        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

        private struct SHFILEINFO
        {

            public IntPtr hIcon;

            public int iIcon;

            public int dwAttributes;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x100)]

            public char[] szDisplayName;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]

            public char[] szTypeName;

        }





        private static Icon GetIconFromFile(string path)
        {

            SHFILEINFO psfi = new SHFILEINFO();

            SHGetFileInfo(path, 0x80, ref psfi, Marshal.SizeOf(psfi), 0x111);

            return Icon.FromHandle(psfi.hIcon);

        }









        [DllImport("shell32.dll", CharSet = CharSet.Auto)]

        private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, int uFlags);









        [DllImport("oleaut32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        internal static extern int OleLoadPictureFile(object fileName, [MarshalAs(UnmanagedType.IDispatch)] ref object iPictureDisp);

        static Color VS_MENUCOLOR = Color.FromArgb(0xec, 0xe9, 0xd8);



        public static void SetControlPicture(CommandBarButton button, string fileName)
        {

            Image image1 = GetImageFromAnyFormat(fileName);

            Bitmap image2 = PrepareImage(image1, VS_MENUCOLOR);

            Bitmap image3 = PrepareMask(image2);

            button.Picture = CreatePictureDisp(image2);

        }

        public static void SetControlPicture(CommandBarButton button, Image icon)
        {
            
            Bitmap image2 = PrepareImage(icon, VS_MENUCOLOR);

            Bitmap image3 = PrepareMask(image2);

            button.Picture = CreatePictureDisp(image2);

        }


        private static Image GetImageFromAnyFormat(string path)
        {

            string str = path.ToLower();

            if (str.EndsWith(".exe") || str.EndsWith(".ico"))
            {

                return GetIconFromFile(path).ToBitmap();

            }

            return Image.FromFile(path, true);

        }





        private static object OleLoadPictureFile(string fileName)
        {

            object iPictureDisp = null;

            OleLoadPictureFile(fileName, ref iPictureDisp);

            return iPictureDisp;

        }





        private static StdPicture CreatePictureDisp(Image image)
        {

            return (StdPicture)ImageConverter.GetIPictureDispFromImage(image);

            //here is another approach:

            //            string tempFileName = Path.GetTempFileName();

            //            image.Save(tempFileName, ImageFormat.Bmp);

            //            return (StdPicture) OleLoadPictureFile(tempFileName);

        }


        private class ImageConverter : AxHost
        {

            // Methods

            internal ImageConverter()

                : base("52D64AAC-29C1-CAC8-BB3A-115F0D3D77CB")
            {

            }



            public static IPictureDisp GetIPictureDispFromImage(Image image)
            {

                return (IPictureDisp)AxHost.GetIPictureDispFromPicture(image);

            }

        }
    }



 



}
